package pe.com.pgn.consolidadorventas.servidorcentral.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import pe.com.pgn.consolidadorventas.servidorcentral.dao.ArchivoDao;
import pe.com.pgn.consolidadorventas.servidorcentral.dao.DatabaseObjectDao;
import pe.com.pgn.consolidadorventas.servidorcentral.dao.EstacionDao;
import pe.com.pgn.consolidadorventas.servidorcentral.dao.GlpVentaDao;
import pe.com.pgn.consolidadorventas.servidorcentral.dbo.Archivo;
import pe.com.pgn.consolidadorventas.servidorcentral.dbo.Estacion;
import pe.com.pgn.consolidadorventas.servidorcentral.dbo.GlpVenta;
import pe.com.pgn.consolidadorventas.servidorcentral.dbo.GlpVentaResumen;
import pe.com.pgn.consolidadorventas.servidorcentral.service.EstacionService;
import pe.com.pgn.consolidadorventas.servidorcentral.util.Constantes;
import pe.com.pgn.consolidadorventas.servidorcentral.util.FechasUtil;
import pe.com.pgn.consolidadorventas.servidorcentral.web.domain.EstacionEstadoEjecucion;
import pe.com.pgn.consolidadorventas.servidorcentral.web.domain.GlpVentasPorDia;

public class EstacionServiceImpl implements EstacionService {

	DatabaseObjectDao databaseObjectDao;
	ArchivoDao archivoDao;
	EstacionDao estacionDao;
	GlpVentaDao glpVentaDao;
    Constantes constantes;
	
	SimpleDateFormat formato;
	SimpleDateFormat formatoFechaHora;
	
	public EstacionServiceImpl(){
		formato = new SimpleDateFormat(Constantes.FORMATO_FECHA);
		formatoFechaHora = new SimpleDateFormat(Constantes.FORMATO_FECHA_HORA);
	}
	
	public void actualizarEstacion(Estacion e) {
		databaseObjectDao.persist(e);
	}
	
	public void registrarEstacion(Estacion e) {
		databaseObjectDao.persist(e);
	}
	
	public void eliminarEstacion(int idEstacion) {
		Estacion e = new Estacion();
		e.setIdEstacion(idEstacion);
		databaseObjectDao.delete(e);
	}
	
	//@Transactional(readOnly = true)
	public Object consultarVentasPorDiaEstacion(int idEstacion, String fecha,int tipoCombustible) {
		
		//SOLO ESTA IMPLEMENTADO PARA GLP
		GlpVentasPorDia rpta = new GlpVentasPorDia();
		//Obtenemos el archivo del dia
		Archivo a = archivoDao.consultarCargaDelDia(idEstacion, fecha, tipoCombustible);
		
		List<GlpVenta> listaDboVentas = null;
		GlpVentaResumen resumen = null;
		
		if(a!=null){
			if(a.getTipoCarga()!=Constantes.TIPO_CARGA_ERROR){			
				//Obtenemos las ventas de ese dia
				listaDboVentas = glpVentaDao.obtenerVentasDelDia(a.getIdArchivo());			
				//Obtenemos el archivo de resumen
				resumen = glpVentaDao.obtenerResumen(a.getIdArchivo());				
			}
		}	
		
		rpta.setListaDboVentas(listaDboVentas);
		rpta.setResumen(resumen);
		
		return rpta;
	}

	//@Transactional(readOnly=true)
	public EstacionEstadoEjecucion obtenerEjecucionEstacionDia(int idEstacion,String fecha,int tipoCombustible) {		
		Estacion e = databaseObjectDao.findById(Estacion.class,idEstacion);
		Archivo a = archivoDao.consultarCargaDelDia(idEstacion, fecha, tipoCombustible);
		EstacionEstadoEjecucion rpta = new EstacionEstadoEjecucion();
		rpta.setEstacion(e);
		rpta.setEstado(a);
		return rpta;
	}
	
	//@Transactional(readOnly=true)
	public List<EstacionEstadoEjecucion> obtenerEstacionesConEstadoConsulta(Date fecha) {
		List<EstacionEstadoEjecucion> rpta = new ArrayList<EstacionEstadoEjecucion>();
	
		List<Estacion> listaEstaciones = (List<Estacion>)databaseObjectDao.findByHqlOrderBy(Estacion.class,"nombreEstacion","asc");
		int limite = listaEstaciones.size();
		
		for(int i=0;i<limite;i++){
			Estacion e = listaEstaciones.get(i);
			Archivo a = archivoDao.consultarCargaDelDia(e.getIdEstacion(),fecha,Constantes.TIPO_ARCHIVO_GLP);
			
			EstacionEstadoEjecucion reg = new EstacionEstadoEjecucion();
			reg.setEstacion(e);
			reg.setEstado(a);
			rpta.add(reg);
		}

		return rpta;
	}
	
	//@Transactional(readOnly=true)
	public List<EstacionEstadoEjecucion> obtenerEstacionesConEstadoConsulta(Date fechaInicio, Date fechaFin) {
		
		Calendar cx = Calendar.getInstance();
		String fecha01 = formato.format(cx.getTime());
		String fecha02 = formato.format(fechaFin);
		
		List<EstacionEstadoEjecucion> rpta = new ArrayList<EstacionEstadoEjecucion>();
		
		List<Estacion> listaEstaciones = (List<Estacion>)databaseObjectDao.findByHqlOrderBy(Estacion.class,"nombreEstacion","asc");
		int limite = listaEstaciones.size();
		for(int i=0;i<limite;i++){
			
			//Obtenemos la estacion
			Estacion e = listaEstaciones.get(i);
			
			//Para cada estacion obtenemos sus ejecuciones en el intervalo dado
			List<Archivo> listaEstadosGlp = null;
			List<Archivo> listaEstadosGnv = null;

			//Visualizamos solo los dias con ejecucion
			if(constantes.getVisualizarDiasSinEjecucion()==0){
				listaEstadosGlp = archivoDao.consultarCargaIntervaloDias(e.getIdEstacion(),fechaInicio,fechaFin,Constantes.TIPO_ARCHIVO_GLP);
				listaEstadosGnv = new ArrayList<Archivo>(); //Por formalidad completar , al parecer este metodo ya no se usara
				//Si la fecha de fin es el dia actual entonces debemos agregar ese dato tambien
				Archivo cargaActualGlp = null;
				if(fecha01.equals(fecha02)){
					if(listaEstadosGlp != null){
						Archivo a = listaEstadosGlp.get(0);
						//Si el primer archivo de la lista no es de la fecha de hoy debemos traerlo
						if(!a.getFechaRegistro().equals(fecha02)){
							cargaActualGlp = archivoDao.consultarCargaDelDia(e.getIdEstacion(),fecha02,Constantes.TIPO_ARCHIVO_GLP);
							if(cargaActualGlp==null){
								cargaActualGlp = new Archivo();
								cargaActualGlp.setFecha(fechaFin);
								cargaActualGlp.setFechaRegistro(formato.format(fechaFin));
								cargaActualGlp.setTipoCarga(-1);
								cargaActualGlp.setDescripcionCarga("No hay ejecucion para este dia");
							}
							
							listaEstadosGlp.add(0, cargaActualGlp);
						}
					}else{
						listaEstadosGlp = new ArrayList<Archivo>();
						cargaActualGlp = archivoDao.consultarCargaDelDia(e.getIdEstacion(),fecha02,Constantes.TIPO_ARCHIVO_GLP);
						if(cargaActualGlp == null){
							cargaActualGlp = new Archivo();
							cargaActualGlp.setFecha(fechaFin);
							cargaActualGlp.setFechaRegistro(formato.format(fechaFin));
							cargaActualGlp.setTipoCarga(-1);
							cargaActualGlp.setDescripcionCarga("No hay ejecucion para este dia");
						}
						listaEstadosGlp.add(cargaActualGlp);
					}
				}
			}else{
				//Aqui consideramos todos los dias incluyendo aquellos sin ejecucion , para glp y gnv
				int diferenciaDias = FechasUtil.obtenerDiasDiferenciaEntreFechas(fechaInicio, fechaFin);
				int index=diferenciaDias;
				GregorianCalendar g = new GregorianCalendar();
				g.setTime(fechaFin);
				Archivo a = null;
				listaEstadosGlp = new ArrayList<Archivo>();
				listaEstadosGnv = new ArrayList<Archivo>();
				
				//Traemos las ventas de glp
				while(index>=0){
					Date d = g.getTime();
					
					//Buscamos para glp
					if(e.getTipoVenta()==Constantes.TIPO_VENTA_GLP || e.getTipoVenta()==Constantes.TIPO_VENTA_GLP_GNV){
						a = archivoDao.consultarCargaDelDia(e.getIdEstacion(),d,Constantes.TIPO_ARCHIVO_GLP);
						if(a==null){
							a = new Archivo();
							a.setFecha(d);
							a.setFechaRegistro(FechasUtil.formatearDateToString(d));
							a.setTipoCarga(-1);
							a.setDescripcionCarga("No hay ejecucion para este dia");
						}
						listaEstadosGlp.add(a);
					}
					
					//Buscamos para gnv
					if(e.getTipoVenta()==Constantes.TIPO_VENTA_GNV || e.getTipoVenta()==Constantes.TIPO_VENTA_GLP_GNV){
						a = archivoDao.consultarCargaDelDia(e.getIdEstacion(),d,Constantes.TIPO_ARCHIVO_GNV);
						if(a==null){
							a = new Archivo();
							a.setFecha(d);
							a.setFechaRegistro(FechasUtil.formatearDateToString(d));
							a.setTipoCarga(-1);
							a.setDescripcionCarga("No hay ejecucion para este dia");
						}
						listaEstadosGnv.add(a);
					}
					
					//Restamos un dia
					g.add(Calendar.DATE,-1);
					index = index - 1;
				}
				
			}
		
			//Aqui estructuramos la lista de objetos para la interfaz del tablero de control
			if(listaEstadosGlp!=null && listaEstadosGnv!=null){
				int dimGlp = listaEstadosGlp.size();
				int dimGnv = listaEstadosGnv.size();
				int dim = dimGlp + dimGnv;
				EstacionEstadoEjecucion aux = null;
				
				//Agregamos al listado de respuesta las ventas de GLP
				for(int j=0;j<dimGlp;j++){
					aux = new EstacionEstadoEjecucion();
					aux.setEstacion(e);
					aux.setEstado(listaEstadosGlp.get(j));
					aux.setTipoVentaRegistro(Constantes.TIPO_VENTA_GLP);
					//Para el rowspan de los datos generales
					if(j==0){
						aux.setNumeroRegistros(dim);
						
						//Para el rowspan de los datos de glp
						aux.setNumeroRegistrosGlp(dimGlp);
						aux.setGrupoDeVentas("GLP");
					}
					rpta.add(aux);
				}
				
				//Agregamos las ventas de GNV
				for(int j=0;j<dimGnv;j++){
					aux = new EstacionEstadoEjecucion();
					aux.setEstacion(e);
					aux.setEstado(listaEstadosGnv.get(j));
					aux.setTipoVentaRegistro(Constantes.TIPO_VENTA_GNV);

					//Para el rowspan de los datos de gnv
					if(j==0){
						
						//En caso de que no haya nada de glp
						if(dimGlp == 0){
							aux.setNumeroRegistros(dim);
						}
						
						//Asignamos los datos de gnv
						aux.setNumeroRegistrosGnv(dimGnv);
						aux.setGrupoDeVentas("GNV");
					}
					rpta.add(aux);
				}
			}	
		}
		
		return rpta;
	}
	
	public List<Estacion> obtenerEstaciones() {
		List<Estacion> lista = (List<Estacion>)databaseObjectDao.findByHqlOrderBy(Estacion.class,"nombreEstacion","asc");
		return lista;
	}

	public Estacion obtenerEstacionXId(int id) {
		Estacion e = (Estacion)databaseObjectDao.findById(Estacion.class,id);
		return e;
	}

	public DatabaseObjectDao getDatabaseObjectDao() {
		return databaseObjectDao;
	}

	public void setDatabaseObjectDao(DatabaseObjectDao databaseObjectDao) {
		this.databaseObjectDao = databaseObjectDao;
	}

	public ArchivoDao getArchivoDao() {
		return archivoDao;
	}

	public void setArchivoDao(ArchivoDao archivoDao) {
		this.archivoDao = archivoDao;
	}
	
	public EstacionDao getEstacionDao() {
		return estacionDao;
	}

	public void setEstacionDao(EstacionDao estacionDao) {
		this.estacionDao = estacionDao;
	}

	public GlpVentaDao getGlpVentaDao() {
		return glpVentaDao;
	}

	public void setGlpVentaDao(GlpVentaDao glpVentaDao) {
		this.glpVentaDao = glpVentaDao;
	}

	public Constantes getConstantes() {
		return constantes;
	}

	public void setConstantes(Constantes constantes) {
		this.constantes = constantes;
	}

	public List<Estacion> obtenerEstacionesXTipoVenta(int tipoVenta) {
		List<Estacion> lista  = (List<Estacion>)databaseObjectDao.findByProperty(Estacion.class,"tipoVenta",tipoVenta);
		return lista;
	}

	public List<Estacion> obtenerEstacionesOrdenCodEstacion(int tipoVenta,String orden) {
		List<Estacion> lista = (List<Estacion>)estacionDao.obtenerEstacionesOrdenCodEstacion(tipoVenta, orden);
		return lista;
	}
}
